/**************************************************************************
*
* Tint Task Manager
* 
* Copyright (C) 2007 Pål Staurland (staura@gmail.com)
* 
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Soft-
* ware"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, subject to the following condi-
* tions:
* 
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* 
**************************************************************************/

#include <cairo.h>
#include <cairo-xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pango/pangocairo.h>
#include <X11/extensions/shape.h>
#include <X11/Xatom.h>
#include <Imlib2.h> 
#include "visual.h"
#include "server.h"
#include "config.h"
#include "task.h"
#include "window.h"

char *get_title (Task *tsk)
{
	if (!tsk->title || !strlen (tsk->title))
		return "Untitled";
	else
		return tsk->title;
}

PangoLayout *get_pango_layout (cairo_t *c, Task *tsk)
{
	PangoLayout *layout;
	PangoFontDescription *desc;

	/* Layout */
	layout = pango_cairo_create_layout (c);
	desc = pango_font_description_from_string (config.font);
	pango_layout_set_font_description (layout, desc);
	pango_font_description_free (desc);
	
	pango_layout_set_text (layout, get_title (tsk), -1);
	
	/* Drawing width */
	pango_layout_set_width (layout, visual.task_drawing_width * PANGO_SCALE);
	
	/* Cut text */
	pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);	
	
	/* Center text */
	if (config.task_text_centered)
		pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
	else
		pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
		
	/* Center vertical */
	//if (!visual.text_height)
	//{
		visual.text_height = tsk->text_width = 0;
		pango_layout_get_pixel_size (layout, &tsk->text_width, &visual.text_height);
		visual.task_vpoint = (config.panel_height / 2.0) - (visual.text_height / 2.0);
	//}
	return layout;
}

void draw_task_icon (Task *tsk, Pixmap *pmap)
{
	if (tsk->icon_data == 0)
		return;

	/* Find pos */
	int pos_x, pos_y, txt_start_pnt;
    if (config.task_text_centered)
    {
    	txt_start_pnt = (config.task_width / 2) - (tsk->text_width / 2);
    	pos_x = txt_start_pnt - (config.icon_size - 5);
    }
    else
    	pos_x = config.task_padding;
    	
    pos_y = (config.panel_height / 2) - (config.icon_size / 2);	
      
	
    /* Render */
    Imlib_Image icon;
    Imlib_Color_Modifier cmod;
   	DATA8 red[256], green[256], blue[256], alpha[256];
   	
	icon = imlib_create_image_using_data (tsk->icon_width, tsk->icon_height, (DATA32 *)tsk->icon_data);
	imlib_context_set_image (icon);
   	imlib_context_set_drawable (*pmap);
    
    cmod = imlib_create_color_modifier ();
	imlib_context_set_color_modifier (cmod);
	imlib_image_set_has_alpha (1);
	imlib_get_color_modifier_tables (red, green, blue, alpha);
	
	int i;
    if (!tsk->active)     
		/* Have no idea what I'm doing here, but it works */                 
    	for(i = 127; i < 256; i++)
				alpha[i] = 100;
  	
	imlib_set_color_modifier_tables (red, green, blue, alpha); 
    
	imlib_render_image_on_drawable_at_size (pos_x, pos_y, config.icon_size, config.icon_size);
	
    imlib_free_color_modifier (); 
    imlib_free_image ();
}

void draw_task_shadow (cairo_t *c, Task *tsk)
{
	PangoLayout *layout;

	layout = get_pango_layout (c, tsk);

	pango_layout_set_text (layout, get_title (tsk), -1);
	cairo_set_source_rgba (c, 0.0, 0.0, 0.0, 0.5);

	pango_cairo_update_layout (c, layout);
	cairo_move_to (c, visual.text_padding + 1, visual.task_vpoint + 1);
	pango_cairo_show_layout (c, layout);
	
	g_object_unref (layout);	
}

void draw_task_title (cairo_t *c, Task *tsk)
{
	PangoLayout *layout;
	
	layout = get_pango_layout (c, tsk);
	
	pango_layout_set_text (layout, get_title (tsk), -1);
	
	if (tsk->active)
		cairo_set_source_rgba (c, 	config.font_active_color[0], 
									config.font_active_color[1], 
									config.font_active_color[2], 
									config.font_active_alpha);

	else 
		cairo_set_source_rgba (c, 	config.font_color[0], 
									config.font_color[1], 
									config.font_color[2], 
									config.font_alpha);
	
	pango_cairo_update_layout (c, layout);
	cairo_move_to (c, visual.text_padding, visual.task_vpoint);
	pango_cairo_show_layout (c, layout);
	
	g_object_unref (layout);
}

void draw_task_background (cairo_t *c, Task *tsk)
{
	if (config.task_background_as_border)
		cairo_rectangle (c, 0, tsk->height - 3, tsk->width, 3);
	else
		cairo_rectangle (c, 0, 0, tsk->width, tsk->height);
	
	if (tsk->active)
		cairo_set_source_rgba (c,	config.task_active_background_color[0],
									config.task_active_background_color[1], 
									config.task_active_background_color[2], 
									config.task_active_background_alpha);
	else 
		cairo_set_source_rgba (c,	config.task_background_color[0],
									config.task_background_color[1], 
									config.task_background_color[2], 
									config.task_background_alpha);
	
	cairo_fill (c);	
}

void draw_panel_background ()
{
	cairo_surface_t *cs;
	cairo_t *c;	
	double alpha;

	cs = cairo_xlib_surface_create (server.dsp, server.pmap, server.visual, 
									config.panel_width, config.panel_height);
	c = cairo_create (cs);
	
	if (!server.got_root_pmap)
	{
		// No wallpaper, no alpha
		alpha = 1.0;
	}
	else
		alpha = config.panel_background_alpha;
	
	cairo_rectangle (c, 0, 0, config.panel_width, config.panel_height);
	cairo_set_source_rgba (	c, 	config.panel_background_color[0], 
								config.panel_background_color[1], 
								config.panel_background_color[2], 
								alpha);
	cairo_fill (c);	
	
	cairo_destroy (c);
	cairo_surface_destroy (cs);		
}

void resize_tasks ()
{
	config.task_width = visual.task_width_copy;
		
	for (; 	(config.task_width + config.task_margin) * task.task_count > 
			(config.panel_width - config.task_margin); 
			config.task_width -= 1);
}

void refresh_props ()
{
	Task *tsk;
	int center_pnt, width, x, icon_width;
	
	width = (config.task_width + config.task_margin) * task.task_count;
	center_pnt = (config.panel_width / 2) - (width / 2);

	if (config.panel_tasks_centered)
		x = center_pnt;
	else
		x = config.task_margin;
	
	tsk = task.tasklist;
	while (tsk)
	{
		tsk->pos_x = x;
		x += config.task_width + config.task_margin;
		tsk->pos_y = config.task_margin;
		
		tsk = tsk->next;
	}
	width = config.task_width - (config.task_padding * 2);
	icon_width = (5 * config.icon) + (config.icon_size * config.icon);
	visual.task_drawing_width = width - icon_width;
}

void refresh_task (Task *tsk, int active)
{
	cairo_surface_t *cs;
	cairo_t *c;
	Pixmap *pmap;
	unsigned int tmp_active;
	
	/* Save original active state and restore later */
	tmp_active = tsk->active;
	tsk->active = active;
	
	if (active)
		pmap = &tsk->active_pmap;
	else
		pmap = &tsk->pmap;
		
	if (*pmap != 0)
		XFreePixmap (server.dsp, *pmap);	
	
	*pmap = server_create_pixmap (tsk->width, tsk->height);
	cs = cairo_xlib_surface_create (server.dsp, *pmap, server.visual, 
									tsk->width, tsk->height);
	c = cairo_create (cs);
	
	/* Copy over root pixmap */
	XCopyArea (	server.dsp, server.pmap, 
				*pmap, server.gc, 
				tsk->pos_x, tsk->pos_y, 
				tsk->width, tsk->height, 0, 0);	
	
	if (tsk->icon_data == 0)
		window_get_icon (tsk);
	
	/* Refresh task visuals */
	if (config.task_background)
		draw_task_background (c, tsk);
	if (config.font_shadow)
		draw_task_shadow (c, tsk);
	if (config.task_show_text)
		draw_task_title (c, tsk);
	if (config.icon)
		draw_task_icon (tsk, pmap);
	
	tsk->need_refresh = 0;
	tsk->active = tmp_active;
	
	cairo_destroy (c);
	cairo_surface_destroy (cs);
}

void visual_draw_tasks ()
{
	Task *tsk;
	
	refresh_props ();
	
	if (config.panel_background)
		draw_panel_background ();
	
	tsk = task.tasklist;
	while (tsk)
	{
		if (tsk->need_refresh)
		{
			refresh_task (tsk, 0);
			refresh_task (tsk, 1);
		}

		if (tsk->active)
			XCopyArea (	server.dsp, tsk->active_pmap, 
						server.pmap, server.gc, 0, 0, 
						tsk->width, tsk->height, tsk->pos_x, tsk->pos_y);	
		else
			XCopyArea (	server.dsp, tsk->pmap, 
						server.pmap, server.gc, 0, 0, 
						tsk->width, tsk->height, tsk->pos_x, tsk->pos_y);				
		
		tsk = tsk->next;
	}
}
